<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta http-equiv="Cache-Control" content="no-siteapp">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=1, minimum-scale=1, maximum-scale=1">
<meta name="referrer" content="never">
<meta name="robots" content="index,follow">
<link rel="shortcut icon" href="/favicon.png?v=198964">
<link rel="apple-itouch-icon" href="/favicon.png?v=198964">
<link href="/bundle/index.min.css" rel="stylesheet">
<link href="https://fonts.loli.net/css?family=Merriweather:300,700,700italic,300italic|Open+Sans:700,400" rel="stylesheet">
<link href="https://cdn.staticfile.org/prism/1.16.0/themes/prism.min.css" rel="stylesheet">
<link href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<script>
    function ensureDate(e){return"object"!=typeof e&&(e=new Date(e)),e}function dateFormat(e,t){void 0===t&&(t=e,e=ensureDate());let n={M:(e=ensureDate(e)).getMonth()+1,d:e.getDate(),h:e.getHours(),m:e.getMinutes(),s:e.getSeconds(),q:Math.floor((e.getMonth()+3)/3),S:e.getMilliseconds()},r=new RegExp("([yMdhmsqS])+","g");return t=t.replace(r,function(t,r){let u=n[r];if(void 0!==u)return t.length>1&&(u=(u="0"+u).substring(u.length-2)),u;if("y"===r){return(e.getFullYear()+"").substring(4-t.length)}return t})}
</script>
    <meta name="keywords" content="React Native爬坑之路 01 生命周期,React Native,">
    <meta name="description" content="React Native爬坑之路 01 生命周期,React Native,">
    <meta name="author" content="江矿先森.">
    <title>React Native爬坑之路 01 生命周期</title>
    <link href="/bundle/iconfont.css" rel="stylesheet">
    <link href="/bundle/reward.css" rel="stylesheet">
    <script src='/bundle/av.min.js'></script>
    <script src='/bundle/valine.min.js'></script>
</head>

<body>
    <article class="container">
        <header class="header-wrap asset">
    <nav class="main-nav">
        <ul class="menu vertical naive">
            <li class="menu-item"><a href="/">Home</a></li>
            <li class="menu-item"><a href="/archive.html">Archive</a></li>
            <li class="menu-item"><a href="/tag.html">Tag</a></li>
            
            <li class="menu-item"><a href="/atom.xml">RSS</a></li>
        </ul>
    </nav>
    <div class="bgs" style="background-image: url(https://pic6.58cdn.com.cn/nowater/webim/big/n_v212fe49b1d6d5492cb1def84eeff4b142.jpg);"></div>
    <div class="vertical">
        <div class="header-wrap-content inner">
            <h3 class="title">Stay before every beautiful thoughts.</h3>
            <h3 class="subtitle">Just be nice, always think twice!</h3>
        </div>
    </div>
</header>
        <article class="main article">
            <h1 class="title">React Native爬坑之路 01 生命周期</h1>
            <section class="info">
                <span class="avatar" style="background-image: url(https://pic1.58cdn.com.cn/nowater/webim/big/n_v2a9773b605e754c8493cf53ca8f5c0d7e.jpg);"></span> <a class="name" href="javascript:;">江矿先森.</a> 
                <span class="date"><script>document.write(dateFormat( 1521689034 *1000, 'yyyy-MM-dd'))</script></span> 
                <span class="tags"><a class="tages" href="/tag/React%20Native/index.html">React Native</a></span>
            </section>
            <article class="content"><p><img src="" data-src="http://7rf9ir.com1.z0.glb.clouddn.com/3-3-component-lifecycle.jpg" alt="" /></p>

<p>如图，可以把组件生命周期大致分为三个阶段:</p>

<ul>
<li>第一阶段:是组件第一次绘制阶段，如图中的上面虚线框内，在这里完成了组件的加载和初始化；</li>
<li>第二阶段:是组件在运行和交互阶段，如图中左下角虚线框，这个阶段组件可以处理用户交互，或者接收事件更新界面；</li>
<li>第三阶段:是组件卸载消亡的阶段，如图中右下角的虚线框中，这里做一些组件的清理工作。</li>
</ul>

<h2>生命周期回调函数</h2>

<p>下面来详细介绍生命周期中的各回调函数。</p>

<ul>
<li>getDefaultProps</li>
</ul>

<p>在组件创建之前，会先调用 getDefaultProps()，这是全局调用一次，严格地来说，这不是组件的生命周期的一部分。在组件被创建并加载候，首先调用 getInitialState()，来初始化组件的状态。</p>

<ul>
<li>componentWillMount</li>
</ul>

<p>然后，准备加载组件，会调用 componentWillMount()，其原型如下:</p>

<pre><code class="language-js">void componentWillMount()
</code></pre>

<p>这个函数调用时机是在组件创建，并初始化了状态之后，在第一次绘制 render() 之前。可以在这里做一些业务初始化操作，也可以设置组件状态。这个函数在整个生命周期中只被调用一次。</p>

<ul>
<li>componentDidMount</li>
</ul>

<p>在组件第一次绘制之后，会调用 componentDidMount()，通知组件已经加载完成。函数原型如下:</p>

<pre><code class="language-js">void componentDidMount()  
</code></pre>

<p>这个函数调用的时候，其虚拟 DOM 已经构建完成，你可以在这个函数开始获取其中的元素或者子组件了。需要注意的是，RN 框架是先调用子组件的 componentDidMount()，然后调用父组件的函数。从这个函数开始，就可以和 JS 其他框架交互了，例如设置计时 setTimeout 或者 setInterval，或者发起网络请求。这个函数也是只被调用一次。这个函数之后，就进入了稳定运行状态，等待事件触发。</p>

<ul>
<li>componentWillReceiveProps</li>
</ul>

<p>如果组件收到新的属性（props），就会调用 componentWillReceiveProps()，其原型如下:</p>

<pre><code class="language-js">void componentWillReceiveProps(  
  object nextProps
)
</code></pre>

<p>输入参数 nextProps 是即将被设置的属性，旧的属性还是可以通过 this.props 来获取。在这个回调函数里面，你可以根据属性的变化，通过调用 this.setState() 来更新你的组件状态，这里调用更新状态是安全的，并不会触发额外的 render() 调用。如下:</p>

<pre><code class="language-js">componentWillReceiveProps: function(nextProps) {  
  this.setState({
    likesIncreasing: nextProps.likeCount &gt; this.props.likeCount
  });
}
</code></pre>

<ul>
<li>shouldComponentUpdate</li>
</ul>

<p>当组件接收到新的属性和状态改变的话，都会触发调用 shouldComponentUpdate(&hellip;)，函数原型如下:</p>

<pre><code class="language-js">boolean shouldComponentUpdate(  
  object nextProps, object nextState
)
</code></pre>

<p>输入参数 nextProps 和上面的 componentWillReceiveProps 函数一样，nextState 表示组件即将更新的状态值。这个函数的返回值决定是否需要更新组件，如果 true 表示需要更新，继续走后面的更新流程。否者，则不更新，直接进入等待状态。</p>

<p>默认情况下，这个函数永远返回 true 用来保证数据变化的时候 UI 能够同步更新。在大型项目中，你可以自己重载这个函数，通过检查变化前后属性和状态，来决定 UI 是否需要更新，能有效提高应用性能。</p>

<ul>
<li>componentWillUpdate</li>
</ul>

<p>如果组件状态或者属性改变，并且上面的 shouldComponentUpdate(&hellip;) 返回为 true，就会开始准更新组件，并调用 componentWillUpdate()，其函数原型如下:</p>

<pre><code class="language-js">void componentWillUpdate(  
  object nextProps, object nextState
)
</code></pre>

<p>输入参数与 shouldComponentUpdate 一样，在这个回调中，可以做一些在更新界面之前要做的事情。需要特别注意的是，在这个函数里面，你就不能使用 this.setState 来修改状态。这个函数调用之后，就会把 nextProps 和 nextState 分别设置到 this.props 和 this.state 中。紧接着这个函数，就会调用 render() 来更新界面了。</p>

<ul>
<li>componentDidUpdate</li>
</ul>

<p>调用了 render() 更新完成界面之后，会调用 componentDidUpdate() 来得到通知，其函数原型如下:</p>

<pre><code class="language-js">void componentDidUpdate(  
  object prevProps, object prevState
)
</code></pre>

<p>因为到这里已经完成了属性和状态的更新了，此函数的输入参数变成了 prevProps 和 prevState。</p>

<ul>
<li>componentWillUnmount</li>
</ul>

<p>当组件要被从界面上移除的时候，就会调用 componentWillUnmount()，其函数原型如下:</p>

<pre><code class="language-js">void componentWillUnmount()  
</code></pre>

<p>在这个函数中，可以做一些组件相关的清理工作，例如取消计时器、网络请求等。</p>

<h2>总结</h2>

<p>介绍完了完整的生命周期，在回头来看一下前面的图，就比较清晰了，把生命周期的回调函数总结成如下表格:</p>

<table>
<thead>
<tr>
<th align="center">生命周期</th>
<th align="center">调用次数</th>
<th align="center">能否setSate?</th>
</tr>
</thead>

<tbody>
<tr>
<td align="center">getDefaultProps</td>
<td align="center">1(全局调用一次)</td>
<td align="center">no</td>
</tr>

<tr>
<td align="center">getInitialState</td>
<td align="center">1</td>
<td align="center">no</td>
</tr>

<tr>
<td align="center">componentWillMount</td>
<td align="center">1</td>
<td align="center">yes</td>
</tr>

<tr>
<td align="center">render</td>
<td align="center">&gt;=1</td>
<td align="center">no</td>
</tr>

<tr>
<td align="center">componentDidMount</td>
<td align="center">1</td>
<td align="center">yes</td>
</tr>

<tr>
<td align="center">componentWillReceiveProps</td>
<td align="center">&gt;=0</td>
<td align="center">yes</td>
</tr>

<tr>
<td align="center">shouldComponentUpdate</td>
<td align="center">&gt;=0</td>
<td align="center">no</td>
</tr>

<tr>
<td align="center">componentWillUpdate</td>
<td align="center">&gt;=0</td>
<td align="center">no</td>
</tr>

<tr>
<td align="center">componentDidUpdate</td>
<td align="center">&gt;=0</td>
<td align="center">no</td>
</tr>

<tr>
<td align="center">componentWillUnmount</td>
<td align="center">1</td>
<td align="center">no</td>
</tr>
</tbody>
</table>
</article>
            <section class="author">
                
                <div class="avatar" style="background-image: url(https://pic1.58cdn.com.cn/nowater/webim/big/n_v2a9773b605e754c8493cf53ca8f5c0d7e.jpg);"></div>
                <a class="name" href="javascript:;">江矿先森.</a>
                <div class="intro">前(台)端(菜), 喜欢瞎折腾新技术. 乜野都识少少, 先可以扮代表.</div>
            </section>
            <section class="social">
                <a href="https://github.com/joname1" target="_blank">
                    <i class="iconfont i-github"></i>
                </a>
                <a href="javascript:alert('你电脑中了不知名的病毒, 并抛出了警告 atob(“d3hJZDogam9uYW1lLmxpYW5ndGFu”)')" target="_blank">
                    <i class="iconfont i-wechat"></i>
                </a>
                <a href="https://www.zhihu.com/people/joname-liangtan" target="_blank">
                    <i class="iconfont i-zhihu"></i>
                </a>
                <a href="javascript:alert('对方不想跟你讲话, 并向你扔来一段乱码 atob(“am9uYW1lLmxpYW5ndGFuQGdtYWlsLmNvbQ”)')" target="_blank">
                    <i class="iconfont i-email"></i>
                </a>
            </section>

            <div class="reward">
                <div class="reward-button">赏
                    <span class="reward-code">
                        <span class="alipay-code">
                            <img class="alipay-img wdp-appear" src="https://pic1.58cdn.com.cn/nowater/webim/big/n_v24d5eae197a764eb194b61e366ff263ba.jpg"><b>支付宝扫码</b>
                        </span>
                    <span class="wechat-code">
                            <img class="wechat-img wdp-appear" src="https://pic1.58cdn.com.cn/nowater/webim/big/n_v20ec7ae162f6a4219b8d0b429a2dbc9b3.jpg"><b>微信扫码</b>
                        </span>
                    </span>
                </div>
                
                <p class="reward-notice">如果文章对你有帮助, 扫上方二维码请我喝杯奶茶吧 :p</p>
            </div>

            <div id="comment"></div>
            
        </article>
    </article>
    <footer class="footer clearfix">
    <span class="copyright">
        <script>
            document.write(new Date().getFullYear());
        </script> <i class="fa fa-copyright"></i> Made with <i class="fa fa-heart"></i> using &ltjoname /&gt
        <span id="runtime_span"></span>
    </span>
</footer>
    <script src="/bundle/index.min.js"></script>
    <script src="https://cdn.staticfile.org/prism/1.16.0/prism.min.js"></script>
    <script>
        new Valine({el: '#comment',appId: 'PieJ3iHvVTJ9C5yBudK6sxaT-MdYXbMMI',appKey: 'Yt25unM4vc9wzBvC2lL20Frc',placeholder: 'ヾﾉ≧∀≦)o来啊, 快活啊, 反正有大把时光!!',path: window.location.pathname,avatar: 'retro',pageSize: 10,guest_info: ['nick', 'mail'],lang: 'en'});
    </script>
</body>

</html>